import os
import subprocess
import xbmcplugin,xbmcgui,xbmcaddon
import shutil
import datetime
import traceback
from string import maketrans

SCRIPT_NAME = "XBMC-RIP-DVDBR"
DEBUG = "true"
settings = xbmcaddon.Addon("script.video.xbmcripdvdbr")

mkv_save_path = settings.getSetting("mkv-save-path") 
mkv_temp_path = settings.getSetting("mkv-temp-path")

#MKV_SAVE_PATH = "/home/xbmc/Movies"
#MKV_TEMP_PATH = "/home/xbmc"


#########################################################
# Function  : GUIEditMovieTitle                         #
#########################################################
# Parameter :                                           #
#                                                       #
# name        sugested name for movie                   #
#                                                       #
# Returns   :                                           #
#                                                       #
# name        name of movie  excluding any extension    #
#                                                       #
#########################################################
def GUIEditMovieTitle(name):
      movieTitle = ""
      kb = xbmc.Keyboard(name)
      kb.setHeading('Enter movie name (check www.themoviedb.org):')
      kb.doModal()
      if (kb.isConfirmed()):
            movieName = kb.getText()
            if len(movieName) == 0:
                  return("")
            kb2 = xbmc.Keyboard(str(datetime.datetime.now().year))
            kb2.setHeading('Enter movie year:')
            kb2.doModal()
            if (kb2.isConfirmed()):
                  movieYear = kb2.getText()
                  if len(movieYear) == 0:
                      return("empty movieyear")
                  movieTitle = movieName + ' (' + movieYear + ')'
            else:
                  movieTitle = ""

      movieTitle = movieTitle.title()

      return(movieTitle)

#########################################################

#########################################################
# Function  : GUIMovieFileName                          #
#########################################################
# Parameter :                                           #
#                                                       #
# name        movie title                               #
#                                                       #
# Returns   :                                           #
#                                                       #
# name        file name of movie, with no special chars #
#                                                       #
#########################################################
def GUIMovieFileName(name):

      intab = " :"
      outtab = "_-"
      trantab = maketrans(intab,outtab)
      moviefilename = name.translate(trantab,"\\\'\"(),!@#$%^&*{}[]\|/?<>`~+=")

      return(moviefilename)

#########################################################



#########################################################
# Function  : GUIlog                                    #
#########################################################
# Parameter :                                           #
#                                                       #
# msg         String to be shown inside GUI             #
#                                                       #
# Returns   : none                                      #
#########################################################
def xbmcLog(msg):

    if (DEBUG == "true"):
       xbmc.log("[%s]: %s\n" % (SCRIPT_NAME,str(msg)))

    return

#########################################################





#########################################################
# Function  : GUINotification                           #
#########################################################
# Parameter :                                           #
#                                                       #
# Info        Text to be shown inside Notification-Box  #
#                                                       #
# Returns   : none                                      #
#########################################################
def GUINotification(Info):

    if (DEBUG == "true"):
        xbmcLog('notification : [' + Info + "]")

    Command = '"xbmc.Notification((' + SCRIPT_NAME + '),' + Info + ',10)"'
    xbmc.executebuiltin( "xbmc.Notification((" + SCRIPT_NAME + ")," + Info + ",1000) ")

    if (DEBUG == "true"):
       xbmcLog('notification-command : [' + Command + "]")

    return

#########################################################

#########################################################
# Function  : GUIMsgBox                                 #
#########################################################
# Parameter :                                           #
#                                                       #
# Info        String to be shown inside Dialog-Box      #
#                                                       #
# Returns   : none                                      #
#########################################################
def GUIMsgBox(Info):
    dialog = xbmcgui.Dialog()

    xbmcLog(Info)
    dialog.ok(SCRIPT_NAME,Info)

    return 0

#########################################################




#########################################################
# Function  : doExit                                    #
#########################################################
# Parameter :                                           #
#                                                       #
#                                                       #
# Returns   : none                                      #
#########################################################

def doExit(task, errorMsg):
        if task._internal_poll(_deadstate=127) is None:
                task.kill()
        GUIMsgBox( errorMsg )
	return 0

#########################################################


xbmcLog("Starting...\n")


#  get movie title (including year)
movieTitle = GUIEditMovieTitle("")
xbmcLog("movieTitle = " + movieTitle + "\n")
if movieTitle == "":
        GUIMsgBox("You must enter a movie name.")
	sys.exit(1)

if movieTitle == "empty movieyear":
        GUIMsgBox("You must enter a year.\nCheck www.themoviedb.org")
	sys.exit(1)

movieFilename = GUIMovieFileName(movieTitle)
xbmcLog("movieFilename = " + movieFilename + "\n")

#  create dir
destFolder = mkv_save_path + "/" + movieTitle
if os.path.exists(destFolder):
	destFolderMoved = destFolder + "_" + GUIMovieFileName(str(datetime.datetime.now()))
	xbmcLog("WARNING: " + destFolder + " already exists... Moving: " + destFolder + " to: " + destFolderMoved)
	shutil.move(destFolder, destFolderMoved)

xbmcLog("Creating dir: " + destFolder + "\n")
os.makedirs(destFolder)


#  start ripping
xbmcLog("Starting to rip... (look at MakeMKV logs)\n")
try:
	progress = xbmcgui.DialogProgress()
	progress.create("Progress", "Please wait...")
	progress.update( 0, "", "Please wait...", "" )
        command = ["makemkvcon", "-r", "--messages=-stdout", "--progress=MakeMKV_progress.txt", "--decrypt", "--minlength=2400", "mkv", "disc:0", "all", destFolder]
        task = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	#wait for the process to start
	xbmcLog("About to sleep for a bit to wait for progress text file...\n")
	xbmc.sleep(10000)		
	xbmcLog("makemkv pid=" + str(task.pid) + "\n")
	percentProgress = 0
	isCancelled = False
	progressFileExists = False
	# had to remove this line, since it didn't work due to a Python bug: while task.poll() is None:
	while task._internal_poll(_deadstate=127) is None:
		xbmcLog("In while ...waiting for makemkv to stop...\n")
                if progress.iscanceled():
                        xbmcLog("User cancelled in main while... Exiting...")
                        task.kill()
                        isCancelled = True
                        break

		if progressFileExists == False:
			xbmcLog("MakeMKV progress file DOES NOT exist... yet... ")
			if os.path.exists(mkv_temp_path + "/MakeMKV_progress.txt"):
				progressFileExists = True
				xbmcLog("MakeMKV progress file exists")
			else:
				xbmcLog("MakeMKV progress file DOES NOT exist... yet...2 ")
				progressFileExists = False
				timeout = 0
				while (not os.path.exists(mkv_temp_path + "/MakeMKV_progress.txt")):
					xbmcLog("MakeMKV progress file DOES NOT exist... yet...3 ")
					if progress.iscanceled():
						xbmcLog("User cancelled in nested while...  Exiting...")
						task.kill()
						isCancelled = True
						break

					xbmc.sleep( 100 )
					timeout += 1
					if timeout > 600:
						#exceeded timeout.. progress file didn't get created
						xbmcLog("Timed out waiting for MakeMKV progress file.")
						break	
				else:
					progressFileExists = True
					xbmcLog("MakeMKV progress file now exists... Took: " + timeout * 10 + " seconds")
		xbmc.sleep( 1000 )
		progressFile = open(mkv_temp_path + "/MakeMKV_progress.txt", "r")
		for line in progressFile:
			pass
		lastLine = line
		#xbmcLog("lastLine = " + lastLine + "\n")
		#xbmcLog("lastLine.split = " + str(lastLine.split(",")) + "\n")
		if "PRGV:" in lastLine:
			currProgress = float(lastLine.split(",")[1])
			#xbmcLog("currProgress = " + str(currProgress) + "\n")
			maxProgress = float(lastLine.split(",")[2])
			#xbmcLog("maxProgress = " + str(maxProgress) + "\n")
			percentProgress = int( (currProgress / maxProgress) * 100 )
			progress.update( percentProgress, "", "Backing up: " + movieTitle, "" )
			xbmc.sleep( 1000 )
			if progress.iscanceled():
				xbmcLog("User cancelled after rip started. Exiting...")
				task.kill()
				isCancelled = True
				break
	progress.close()
	if os.path.isfile(mkv_temp_path + "/MakeMKV_progress.txt"):
		os.remove(mkv_temp_path + "/MakeMKV_progress.txt")
	if isCancelled == True:
		sys.exit(0)
	output = task.stdout.read().split(",")  #converts stdout to list object
	xbmcLog("output = " + str(output) + "\n")
	xbmcLog("stderr = " + str(task.stderr.read()) + "\n")
	checks = 0
	for line in output:
		if "Failed to save title" in line:
			checks -= 1
		if "Copy complete" in line:
			checks += 1
		if "titles saved" in line:
			checks += 1
		if "Failed to open disc" in line:
        		errorMsg = "ERROR: No Disc was found in drive."
			doExit(task, errorMsg)
			break
			#sys.exit(1)


except Exception as e:
        xbmcLog(traceback.print_exc())
        errorMsg = "EXCEPTION: " + str(e)
	doExit(task, errorMsg)
	#sys.exit(1)

if checks >= 2: #all went well
	#  eject
	xbmcLog("Ejecting...\n")
	subprocess.call(["eject"])

	#add movie to XBMC
	xbmc.executebuiltin('UpdateLibrary(video)')
else:
	try:
		if errorMsg <> "ERROR: Bad Disc or no Disc was found in drive.":
			GUIMsgBox("An error occured saving the disc.\nCall the programmer and tell him to check logs.")
		#sys.exit(1)
	except Exception as e:
		GUIMsgBox("An error occured saving the disc.\nCall the programmer and tell him to check logs.")
		xbmcLog(e)
		

xbmcLog("Done.\n")
#sys.exit(0)
